home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / makeindex / scanid.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-04-26  |  11.4 KB  |  593 lines

  1. /*
  2.  *
  3.  * Copyright (C) 1987     Pehong Chen    (phc@renoir.berkeley.edu)
  4.  * Computer Science Division
  5.  * University of California, Berkeley
  6.  *
  7.  */
  8.  
  9. #include        "mkind.h"
  10. #include        "scanid.h"
  11.  
  12.  
  13. int            idx_lc;        /* line count */
  14. int            idx_tc;        /* total entry count */
  15. int            idx_ec;        /* erroneous entry count */
  16. int            idx_dc;        /* number of dots printed so far */
  17.  
  18. static    int        first_entry = TRUE;
  19. static    int        comp_len;
  20. static    char        key[ARGUMENT_MAX];
  21. static    char        no[NUMBER_MAX];
  22.  
  23. NODE_PTR        head;
  24. NODE_PTR        tail;
  25.  
  26.  
  27. void
  28. scan_idx()
  29. {
  30.         char         keyword[STRING_MAX];
  31.     int        c;
  32.     int        i = 0;
  33.     int        not_eof = TRUE;
  34.     int        arg_count = -1;
  35.  
  36.     MESSAGE("Scanning input file %s...", idx_fn);
  37.     idx_lc = idx_tc = idx_ec = idx_dc = 0;
  38.     comp_len = strlen(page_comp);
  39.     while (not_eof) {
  40.         switch (c = GET_CHAR(idx_fp)) {
  41.         case EOF:
  42.             if (arg_count == 2) {
  43.                 idx_lc++;
  44.                 if (make_key())
  45.                     IDX_DOT(DOT_MAX);
  46.                 arg_count = -1;
  47.             } else
  48.                 not_eof = FALSE;
  49.             break;
  50.  
  51.         case LFD:
  52.             idx_lc++;
  53.             if (arg_count == 2) {
  54.                 if (make_key())
  55.                     IDX_DOT(DOT_MAX);
  56.                 arg_count = -1;
  57.             } else if (arg_count > -1) {
  58.                     IDX_ERROR("Missing arguments -- need two (premature LFD).\n", NULL);
  59.                 arg_count = -1;
  60.             }
  61.         case TAB:
  62.         case SPC:
  63.             break;
  64.  
  65.         default:
  66.             switch (arg_count) {
  67.             case -1:
  68.                 i = 0;
  69.                 keyword[i++] = (char)c;
  70.                 arg_count++;
  71.                 idx_tc++;
  72.                 break;
  73.             case 0:
  74.                 if (c == idx_aopen) {
  75.                     arg_count++;
  76.                         keyword[i] = NULL;
  77.                     if (STREQ(keyword, idx_keyword)) {
  78.                         if (! scan_arg1()) {
  79.                             arg_count = -1;
  80.                         }
  81.                     } else {
  82.                         IDX_SKIPLINE;
  83.                         IDX_ERROR("Unknown index keyword %s.\n", keyword);
  84.                     }
  85.                 } else {
  86.                     if (i < STRING_MAX)
  87.                         keyword[i++] = (char)c;
  88.                     else {
  89.                         IDX_SKIPLINE;
  90.                         IDX_ERROR2("Index keyword %s too long (max %d).\n",
  91.                                     keyword, STRING_MAX);
  92.                     }
  93.                 }
  94.                 break;
  95.             case 1:
  96.                 if (c == idx_aopen) {
  97.                     arg_count++;
  98.                     if (! scan_arg2()) {
  99.                         arg_count = -1;
  100.                     }
  101.                 } else {
  102.                     IDX_SKIPLINE;
  103.                     IDX_ERROR("No opening delimiter for second argument (illegal char `%c').\n", c);
  104.                 }
  105.                 break;
  106.             case 2:
  107.                 IDX_SKIPLINE;
  108.                 IDX_ERROR("No closing delimiter for second argument (illegal character `%c').\n", c);
  109.                 break;
  110.             }
  111.             break;
  112.         }
  113.     }
  114.  
  115.     /* fixup the total counts */
  116.     idx_tt += idx_tc;
  117.     idx_et += idx_ec;
  118.  
  119.     DONE(idx_tc - idx_ec, "entries accepted", idx_ec, "rejected");
  120.     CLOSE(idx_fp);
  121. }
  122.  
  123. static int
  124. make_key()
  125. {
  126.     NODE_PTR    ptr;
  127.     int        i;
  128.  
  129.     /* allocate and initialize a node */
  130.     if ((ptr = (NODE_PTR) malloc(sizeof(NODE))) == NULL)
  131.         FATAL("Not enough core...abort.\n", "");
  132.  
  133.     for (i = 0; i < FIELD_MAX; i++) {
  134.         ptr->data.sf[i][0] = NULL;
  135.         ptr->data.af[i][0] = NULL;
  136.     }
  137.     ptr->data.lpg[0] = ptr->data.encap[0] = NULL;
  138.     ptr->data.count = 0;
  139.     ptr->data.type = EMPTY;
  140.  
  141.     /* process index key */
  142.     if (! scan_key(&(ptr->data)))
  143.             return (FALSE);
  144.  
  145.     /* determine group type */
  146.     ptr->data.group = group_type(ptr->data.sf[0]);
  147.  
  148.     /* process page number */
  149.     strcpy(ptr->data.lpg, no);
  150.     if (! scan_no(no, ptr->data.npg, &(ptr->data.count), &(ptr->data.type)))
  151.         return (FALSE);
  152.  
  153.     if (first_entry) {
  154.         head = tail = ptr;
  155.         first_entry = FALSE;
  156.     } else {
  157.         tail->next = ptr;
  158.         tail = ptr;
  159.     }
  160.     ptr->data.lc = idx_lc;
  161.     ptr->data.fn = idx_fn;
  162.     tail->next = NULL;
  163.  
  164.     return (TRUE);
  165. }
  166.  
  167.  
  168. static int
  169. scan_key(data)
  170.     FIELD_PTR    data;
  171. {
  172.     int        i = 0;        /* current level */
  173.     int        n = 0;        /* index to the key[] array */
  174.     int        second_round = FALSE;
  175.     int        last = FIELD_MAX - 1;
  176.  
  177.     while (TRUE) {
  178.         if (key[n] == NULL)
  179.                 break;
  180.         if (key[n] == idx_encap) {
  181.             n++;
  182.             if (scan_field(&n, data->encap, FALSE, FALSE, FALSE))
  183.                     break;
  184.             else
  185.                 return (FALSE);
  186.         }
  187.         if (key[n] == idx_actual) {
  188.             n++;
  189.             if (! scan_field(&n, data->af[i], TRUE, TRUE, FALSE))
  190.                 return (FALSE);
  191.         } else {
  192.             /* Next nesting level */
  193.             if (second_round) {
  194.                 i++;
  195.                 n++;
  196.             }
  197.             if (i == last) {
  198.                 if (! scan_field(&n, data->sf[i], FALSE, TRUE, TRUE))
  199.                     return (FALSE);
  200.             } else {
  201.                 if (! scan_field(&n, data->sf[i], TRUE, TRUE, TRUE))
  202.                     return (FALSE);
  203.             }
  204.             second_round = TRUE;
  205.         }
  206.     }
  207.  
  208.     /* check for empty fields which shouldn't be empty */
  209.     if (*data->sf[0] == NULL) {
  210.         NULL_RTN;
  211.     }
  212.     for (i = 1; i < FIELD_MAX-1; i++)
  213.         if ((*data->sf[i] == NULL) &&
  214.             ((*data->af[i] != NULL) || (*data->sf[i+1] != NULL))) {
  215.             NULL_RTN;
  216.         }
  217.  
  218.     /* i == FIELD_MAX-1 */
  219.     if ((*data->sf[i] == NULL) && (*data->af[i] != NULL)) {
  220.         NULL_RTN;
  221.     }
  222.     return (TRUE);
  223. }
  224.  
  225.  
  226. static int
  227. scan_field(n, field, ck_level, ck_encap, ck_actual)
  228.     int        *n;
  229.     char        field[];
  230.     int        ck_level;
  231.     int        ck_encap;
  232.     int        ck_actual;
  233. {
  234.     int        i = 0;
  235.     int        nbsh;        /* backslash count */
  236.  
  237.     while (TRUE) {
  238.         if (compress_blanks && (key[*n] == SPC))
  239.             ++*n;
  240.  
  241.         nbsh = 0;
  242.         while (key[*n] == idx_escape) {
  243.             nbsh++;
  244.             field[i++] = key[*n];
  245.             ++*n;
  246.         }
  247.  
  248.         if (key[*n] == idx_quote) {
  249.             if (nbsh%2 == 0)
  250.                 field[i++] = key[++*n];
  251.             else
  252.                 field[i++] = key[*n];
  253.         } else if ((ck_level && (key[*n] == idx_level)) ||
  254.                (ck_encap && (key[*n] == idx_encap)) ||
  255.                (ck_actual && (key[*n] == idx_actual)) ||
  256.                (key[*n] == NULL)) {
  257.             if ((i > 0) && compress_blanks && (field[i-1] == SPC))
  258.                 field[i-1] = NULL;
  259.             else
  260.                 field[i] = NULL;
  261.                 return (TRUE);
  262.         } else {
  263.                 field[i++] = key[*n];
  264.             if ((! ck_level) && (key[*n] == idx_level)) {
  265.                 IDX_ERROR2("Extra `%c' at position %d of first argument.\n", idx_level, *n+1);
  266.                 return (FALSE);
  267.             } else if ((! ck_encap) && (key[*n] == idx_encap)) {
  268.                 IDX_ERROR2("Extra `%c' at position %d of first argument.\n", idx_encap, *n+1);
  269.                 return (FALSE);
  270.             } else if ((! ck_actual) && (key[*n] == idx_actual)) {
  271.                 IDX_ERROR2("Extra `%c' at position %d of first argument.\n", idx_actual, *n+1);
  272.                 return (FALSE);
  273.             }
  274.         }
  275.         ++*n;
  276.     }
  277. }
  278.  
  279. int
  280. group_type(str)
  281.     char        *str;
  282. {
  283.     int        i = 0;
  284.  
  285.     while ((str[i] != NULL) && ISDIGIT(str[i]))
  286.         i++;
  287.  
  288.     if (str[i] == NULL) {
  289.         sscanf(str, "%d", &i);
  290.         return (i);
  291.     } else
  292.         if (ISSYMBOL(str[0]))
  293.             return (SYMBOL);
  294.          else
  295.             return (ALPHA);
  296. }
  297.  
  298. static int
  299. scan_no(no, npg, count, type)
  300.     char        no[];
  301.     short        npg[];
  302.     short        *count;
  303.     short        *type;
  304. {
  305.     int        i = 1;
  306.  
  307.     if (isdigit(no[0])) {
  308.         *type = ARAB;
  309.         if (! scan_arabic(no, npg, count))
  310.             return (FALSE);
  311.     /* simple heuristic to determine if a letter is Roman or Alpha */
  312.     } else if (IS_ROMAN_LOWER(no[0]) && (! IS_COMPOSITOR)) {
  313.         *type = ROML;
  314.         if (! scan_roman_lower(no, npg, count))
  315.             return (FALSE);
  316.     /* simple heuristic to determine if a letter is Roman or Alpha */
  317.     } else if (IS_ROMAN_UPPER(no[0]) && ((no[0] == ROMAN_I) || (! IS_COMPOSITOR))) {
  318.         *type = ROMU;
  319.         if (! scan_roman_upper(no, npg, count))
  320.             return (FALSE);
  321.     } else if (IS_ALPHA_LOWER(no[0])) {
  322.         *type = ALPL;
  323.         if (! scan_alpha_lower(no, npg, count))
  324.             return (FALSE);
  325.     } else if (IS_ALPHA_UPPER(no[0])) {
  326.         *type = ALPU;
  327.         if (! scan_alpha_upper(no, npg, count))
  328.             return (FALSE);
  329.     } else {
  330.         IDX_ERROR("Illegal page number %s.\n", no);
  331.         return (FALSE);
  332.     }
  333.     return (TRUE);
  334. }
  335.  
  336.  
  337. static int
  338. scan_arabic(no, npg, count)
  339.     char        no[];
  340.     short        npg[];
  341.     short        *count;
  342. {
  343.     short        i = 0;
  344.     char        str[ARABIC_MAX];
  345.  
  346.     while ((no[i] != NULL) && (i < ARABIC_MAX) && (! IS_COMPOSITOR)) {
  347.         if (isdigit(no[i])) {
  348.             str[i] = no[i];
  349.             i++;
  350.         } else {
  351.             IDX_ERROR2("Illegal Arabic digit: position %d in %s.\n", i+1, no);
  352.             return (FALSE);
  353.         }
  354.     }
  355.     if (i >= ARABIC_MAX) {
  356.         IDX_ERROR2("Arabic page number %s too big (max %d digits).\n",
  357.                no, ARABIC_MAX);
  358.         return (FALSE);
  359.     }
  360.     str[i] = NULL;
  361.  
  362.     ENTER(strtoint(str) + page_offset[ARAB]);
  363.  
  364.     if (IS_COMPOSITOR)
  365.         return (scan_no(&no[i+comp_len], npg, count, &i));
  366.     else
  367.         return (TRUE);
  368. }
  369.  
  370.  
  371. static int
  372. scan_roman_lower(no, npg, count)
  373.     char        no[];
  374.     short        npg[];
  375.     short        *count;
  376. {
  377.     short        i = 0;
  378.     int        inp = 0;
  379.     int        prev = 0;
  380.     int        new;
  381.  
  382.     while ((no[i] != NULL) && (i < ROMAN_MAX) && (! IS_COMPOSITOR)) {
  383.         if ((IS_ROMAN_LOWER(no[i])) && (new = ROMAN_LOWER_VAL(no[i]))) {
  384.             if (prev == 0)
  385.                 prev = new;
  386.             else {
  387.                 if (prev < new) {
  388.                     prev = new - prev;
  389.                     new = 0;
  390.                 }
  391.                 inp += prev;
  392.                 prev = new;
  393.             }
  394.         } else {
  395.             IDX_ERROR2("Illegal Roman number: position %d in %s.\n", i+1, no);
  396.             return (FALSE);
  397.         }
  398.         i++;
  399.     }
  400.     if (i == ROMAN_MAX) {
  401.         IDX_ERROR2("Roman page number %s too big (max %d digits).\n",
  402.                no, ROMAN_MAX);
  403.         return(FALSE);
  404.     }
  405.     inp += prev;
  406.  
  407.     ENTER(inp + page_offset[ROML]);
  408.  
  409.     if (IS_COMPOSITOR)
  410.         return (scan_no(&no[i+comp_len], npg, count, &i));
  411.     else
  412.         return (TRUE);
  413. }
  414.  
  415.  
  416. static int
  417. scan_roman_upper(no, npg, count)
  418.     char        no[];
  419.     short        npg[];
  420.     short        *count;
  421. {
  422.     short        i = 0;
  423.     int        inp = 0;
  424.     int        prev = 0;
  425.  
  426.     int        new;
  427.  
  428.     while ((no[i] != NULL) && (i < ROMAN_MAX) && (! IS_COMPOSITOR)) {
  429.         if ((IS_ROMAN_UPPER(no[i])) && (new = ROMAN_UPPER_VAL(no[i]))) {
  430.             if (prev == 0)
  431.                 prev = new;
  432.             else {
  433.                 if (prev < new) {
  434.                     prev = new - prev;
  435.                     new = 0;
  436.                 }
  437.                 inp += prev;
  438.                 prev = new;
  439.             }
  440.         } else {
  441.             IDX_ERROR2("Illegal Roman number: position %d in %s.\n", i+1, no);
  442.             return (FALSE);
  443.         }
  444.         i++;
  445.     }
  446.     if (i == ROMAN_MAX) {
  447.         IDX_ERROR2("Roman page number %s too big (max %d digits).\n",
  448.                no, ROMAN_MAX);
  449.         return(FALSE);
  450.     }
  451.     inp += prev;
  452.  
  453.     ENTER(inp + page_offset[ROMU]);
  454.  
  455.     if (IS_COMPOSITOR)
  456.         return (scan_no(&no[i+comp_len], npg, count, &i));
  457.     else
  458.         return (TRUE);
  459. }
  460.  
  461.  
  462. static int
  463. scan_alpha_lower(no, npg, count)
  464.     char        no[];
  465.     short        npg[];
  466.     short        *count;
  467. {
  468.     short        i;
  469.  
  470.     ENTER(ALPHA_VAL(no[0]) + page_offset[ALPL]);
  471.  
  472.     i = 1;
  473.     if (IS_COMPOSITOR)
  474.         return (scan_no(&no[comp_len+1], npg, count, &i));
  475.     else
  476.         return (TRUE);
  477. }
  478.  
  479.  
  480. static int
  481. scan_alpha_upper(no, npg, count)
  482.     char        no[];
  483.     short        npg[];
  484.     short        *count;
  485. {
  486.     short        i;
  487.  
  488.     ENTER(ALPHA_VAL(no[0]) + page_offset[ALPU]);
  489.  
  490.     i = 1;
  491.     if (IS_COMPOSITOR)
  492.         return (scan_no(&no[comp_len+1], npg, count, &i));
  493.     else
  494.         return (TRUE);
  495. }
  496.  
  497.  
  498. static int
  499. scan_arg1()
  500. {
  501.     int        i = 0;
  502.     int        n = 0;        /* delimiter count */
  503.     int        a;
  504.  
  505.     if (compress_blanks)
  506.         while (((a = GET_CHAR(idx_fp)) == SPC) || (a == TAB));
  507.     else
  508.         a = GET_CHAR(idx_fp);
  509.  
  510.     while (i < ARGUMENT_MAX) {
  511.         if (a == idx_aopen) {
  512.             /* opening delimiters within the argument list */
  513.             key[i++] = (char)a;
  514.             n++;
  515.         } else if (a == idx_aclose) {
  516.             if (n == 0) {
  517.                 if (compress_blanks && key[i-1] == SPC)
  518.                     key[i-1] = NULL;
  519.                 else
  520.                     key[i] = NULL;
  521.                 return (TRUE);
  522.             } else {
  523.                 key[i++] = (char)a;
  524.                 n--;
  525.             }
  526.         } else switch (a) {
  527.             case LFD:
  528.                 idx_lc++;
  529.                 IDX_ERROR("Incomplete first argument (premature LFD).\n", "");
  530.                 return (FALSE);
  531.             case TAB:
  532.             case SPC:
  533.                 /* compress successive SPC's to one SPC */
  534.                 if (compress_blanks && (i > 0) &&
  535.                     (key[i-1] != SPC) && (key[i-1] != TAB)) {
  536.                     key[i++] = SPC;
  537.                     break;
  538.                 }
  539.             default:
  540.                 key[i++] = (char)a;
  541.                 break;
  542.             }
  543.         a = GET_CHAR(idx_fp);
  544.     }
  545.     /* Skip to end of line */
  546.     while (GET_CHAR(idx_fp) != LFD);
  547.     idx_lc++;
  548.     IDX_ERROR("First argument too long (max %d).\n", ARGUMENT_MAX);
  549.     return (FALSE);
  550. }
  551.  
  552.  
  553. static int
  554. scan_arg2()
  555. {
  556.     int        i = 0;
  557.     int        a;
  558.     int        hit_blank = FALSE;
  559.  
  560.     while (((a = GET_CHAR(idx_fp)) == SPC) || (a == TAB));
  561.  
  562.     while (i < NUMBER_MAX) {
  563.         if (a == idx_aclose) {
  564.             no[i] = NULL;
  565.             return (TRUE);
  566.         } else switch (a) {
  567.             case LFD:
  568.                 idx_lc++;
  569.                 IDX_ERROR("Incomplete second argument (premature LFD).\n", "");
  570.                 return (FALSE);
  571.             case TAB:
  572.             case SPC:
  573.                 hit_blank = TRUE;
  574.                 break;
  575.             default:
  576.                 if (hit_blank) {
  577.                     while (GET_CHAR(idx_fp) != LFD);
  578.                     idx_lc++;
  579.                     IDX_ERROR("Illegal space within numerals in second argument.\n", "");
  580.                     return (FALSE);
  581.                 }
  582.                 no[i++] = (char)a;
  583.                 break;
  584.             }
  585.         a = GET_CHAR(idx_fp);
  586.     }
  587.     /* Skip to end of line */
  588.     while (GET_CHAR(idx_fp) != LFD);
  589.     idx_lc++;
  590.     IDX_ERROR("Second argument too long (max %d).\n", NUMBER_MAX);
  591.     return (FALSE);
  592. }
  593.